package com.hundsun.bible.facade.impl.account;

import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.hundsun.bible.Page;
import com.hundsun.bible.PageUtil;
import com.hundsun.bible.dao.counter.RefundDao;
import com.hundsun.bible.domain.Enum.EnumInstitution;
import com.hundsun.bible.domain.Enum.EnumRefundResult;
import com.hundsun.bible.domain.Enum.EnumSubTransCode;
import com.hundsun.bible.domain.model.RefundMoney;
import com.hundsun.bible.domain.model.acctrans.AccountTransResult;
import com.hundsun.bible.domain.model.acctrans.FreezeBalanceReq;
import com.hundsun.bible.domain.model.counter.Refund;
import com.hundsun.bible.domain.util.Money;
import com.hundsun.bible.exception.ManagerException;
import com.hundsun.bible.facade.acctrans.AccountTransManager;
import com.hundsun.bible.facade.counter.RefundManager;
import com.hundsun.bible.facade.trade.RefundMoneyManager;

public class ReFundManagerImpl implements RefundManager {
	private AccountTransManager accountTransManager;
	private RefundMoneyManager refundMoneyManager;
	private RefundDao refundManagerDao;
	private TransactionTemplate transactionTemplate;
	protected final Log log = LogFactory.getLog(getClass());

	public TransactionTemplate getTransactionTemplate() {
		return transactionTemplate;
	}

	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
	}

	public RefundMoneyManager getRefundMoneyManager() {
		return refundMoneyManager;
	}

	public void setRefundMoneyManager(RefundMoneyManager refundMoneyManager) {
		this.refundMoneyManager = refundMoneyManager;
	}

	public AccountTransManager getAccountTransManager() {
		return accountTransManager;
	}

	public void setAccountTransManager(AccountTransManager accountTransManager) {
		this.accountTransManager = accountTransManager;
	}

	public RefundDao getRefundManagerDao() {
		return refundManagerDao;
	}

	public void setRefundManagerDao(RefundDao refundManagerDao) {
		this.refundManagerDao = refundManagerDao;
	}

	public Log getLog() {
		return log;
	}

	public PageUtil<Refund> getRefundSearchPage(Map<String, String> searchMap,
			Page page) {
		try {
			return this.refundManagerDao.getRefundSearchPage(searchMap, page);
		} catch (Exception e) {
			log.error(e.getMessage());
			throw new ManagerException(e);
		}
	}

	public String refund(String userName, boolean result,
			List<Long> withdrawIdList) {
		// TODO Auto-generated method stub
		return null;
	}

	public String refundConfirm(List<Long> refundIds, final String result,
			final String operator) {

		StringBuffer error_msg = new StringBuffer(); // 错误反馈

		for (final Long id : refundIds) {
			String message_trans = refundTransAction(result, operator, id);
			if (!message_trans.equals("true")) {
				error_msg.append(message_trans);
			}
		}
		return (error_msg.length() == 0 ? "success" : error_msg.toString());
	}

	/**
	 * 冲退事务处理
	 * 
	 * @param result
	 * @param operator
	 * @param id
	 * @return
	 */
	private String refundTransAction(final String result,
			final String operator, final Long id) {
		String message_trans = (String) transactionTemplate
				.execute(new TransactionCallback() {
					public Object doInTransaction(TransactionStatus status) {
						try {
							FreezeBalanceReq req;
						Refund refund = refundManagerDao.getReFundById(id);
							RefundMoney refundMoney = new RefundMoney();
		  				    refundMoney.setRefundId(refund.getTrandRefundId());
							refund.setOperator(operator);
							req = new FreezeBalanceReq();
							Money money = new Money();
							money.setCent(refund.getRefundAmount());
							req.setAmount(money);
							req.setAccountNo(refund.getAccountNo());
							req.setOperator(operator);
							String errorString = unfreeze(req, id, refund);

							//解冻处理失败，仅提示不改流水状态
							if (!errorString.equals("true")) {
								//updateRefund(refund,"F","解冻处理失败");
								//updateTradeRefund(refundMoney, (short)-1, "解冻处理失败");
								log.error("解冻处理失败");
								return errorString + "<br>";
							}

							if (result.equals("true")) { //判断支付机构是否返回成功
								errorString = trans(req, id, refund);
								
								//扣款处理失败，仅提示不改流水状态
								if (!errorString.equals("true")) {
									//updateRefund(refund,"F","扣款处理失败");
									//updateTradeRefund(refundMoney, (short)-1, "扣款处理失败");
									status.setRollbackOnly();// 事务回滚
									log.error("扣款处理失败");
									return errorString + "<br>";
								}
								updateRefund(refund,"S","支付机构处理成功");
								updateTradeRefund(refundMoney, (short)1, "支付机构处理成功");
								
							}else {
								updateRefund(refund,"F","支付机构处理失败");
								updateTradeRefund(refundMoney, (short)-1, "支付机构处理失败");
								log.error("支付机构处理失败");
							}

						} catch (Exception e) {
							log.error("processInstResponseTrans处理失败", e);
							status.setRollbackOnly();// 事务回滚
							if (!result.equals("true")) {
								return EnumRefundResult.REF_RESULT_REFUND_FAIL_ACCOUNT_TRANS_ERROR;
							} else {
								return EnumRefundResult.REF_RESULT_REFUND_SUCCESS_ACCOUNT_TRANS_ERROR;
							}
						}
						return "true";
					}
				});
		return message_trans;
	}

	/**
	 * 扣款
	 * 
	 * @param req
	 * @param id
	 * @param refund
	 * @return
	 */
	private String trans(FreezeBalanceReq req, Long id, Refund refund) {
		req.setSubTransCode(EnumSubTransCode.TXCODE_RETURN_INSTITUTION_SUCCESS);
		req.setBankType(EnumInstitution.getByName(refund.getBankType()));
		req.setInnerBizNo(refund.getBankBillNo());
		req.setPositive(false);
		AccountTransResult re = accountTransManager.execute(req);
		if (!re.getCode().equals("TXN_RESULT_SUCCESS")) {
			return "冲退流水ID:" + id.toString() + "发生错误，原因：" + re.getMessage();
		} else {
			refund.setStatus("S");
			refundManagerDao.updateRefund(refund);
			return "true";
		}
	}

	/**
	 * 解冻
	 * 
	 * @param req
	 * @param id
	 * @param refund
	 * @return
	 */
	private String unfreeze(FreezeBalanceReq req, Long id, Refund refund) {
		req
				.setSubTransCode(EnumSubTransCode.TXCODE_ACCOUNT_RETURN_INSTITUTION_UNFREEZE);
		req.setInnerBizNo(refund.getBankBillNo());
		req.setPositive(false);
		AccountTransResult re = accountTransManager.execute(req);

		if (!re.getCode().equals("TXN_RESULT_SUCCESS")) {
			return "支付流水ID:" + refund.getBankBillNo() + "发生错误，原因：" + re.getMessage();
		} else {
			refund.setStatus("F");
			refundManagerDao.updateRefund(refund);
			return "true";
		}
	}

	/**
	 * 修改充退流水状态
	 */
	private void updateRefund(Refund refund, String status,
			String memo) {
		refund.setStatus(status);
		refund.setMemo(memo);
		refundManagerDao.updateRefundById(refund);
	}

	/**
	 * 修改交易退款流水状态 -1 失败 1成功
	 */
	private void updateTradeRefund(RefundMoney refundMoney, short stus,
			String memo) {
		refundMoney.setOtherStauts(stus);
		refundMoney.setErrorMessage(memo);
		refundMoneyManager.editRefundMoneyByRefundId(refundMoney);
	}

}
